
header{
	
/**********************************************************
 * ActionScript Development Tool 
 * Copyright (C) 2005 asdt.org 
 * 
 * http://www.asdt.org
 * http://sourceforge.net/projects/aseclipseplugin/
 *
 * This program is free software; 
 * you can redistribute it and/or modify it under the terms of 
 * the GNU General Public License as published by the 
 * Free Software Foundation; either version 2 of the License, 
 * or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the 
 * Free Software Foundation, Inc., 
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 
 * 
 * Created on 29 sept 2005
 * 
 **********************************************************/


package org.asdt.core.internal.antlr; 

import java.util.List;
import java.util.ArrayList;
}

 
/**
 *	@author Martin Schnabel
 */
class AS2Parser extends Parser;

options {
	k = 3;
	exportVocab = AS2;
	buildAST = true;
	defaultErrorHandler=true;
}

tokens {
	COMPILATION_UNIT;
	IMPORTS; IMPORT;
	CLASS_DEF; INTERFACE_DEF; 
	EXTENDS_CLAUSE; IMPLEMENTS_CLAUSE;
	MODIFIERS; VAR_DEF; VAR_SUB_DEF; METHOD_DEF; PARAMS; PARAM; TYPE_SPEC;
	BLOCK; EXPR; ELIST; EXPR_STMNT;
	NEW_EXPR; ENCPS_EXPR;
	VAR_INIT;
	METHOD_CALL; ARRAY_ACC;
	UNARY_PLUS; UNARY_MINUS; POST_INC; POST_DEC;
	ARRAY_LITERAL; ELEMENT; OBJECT_LITERAL; OBJECT_FIELD; FUNC_DEF;
	FOR_INIT; FOR_CONDITION; FOR_ITERATOR;
	THIS="this"; NULL="null"; UNDEFINED="undefined"; TRUE="true"; FALSE="false";
	INSTANCEOF="instanceof";
	DELETE="delete"; TYPEOF="typeof";
	THROW="throw";
	FUNCTION="function";
	NEW="new";
}
{
	boolean isInterface = false;
	boolean isIntrinsic = false;
	boolean isTopLevel = false;
	
	private void setRegionInfo(AST ast,AST startAST,AST endAST){
		if(ast instanceof ASSourceAST){
			ASSourceAST as2ast	= (ASSourceAST)ast;
			if(startAST!=null){
				as2ast.setStartOffset(startAST);
				if(endAST==null)
					as2ast.setEndOffset(startAST);
			}
			if(endAST!=null)
				as2ast.setEndOffset(endAST);

		}	
	}
}
/**
 * this is the start rule for this parser
 */
compilationUnit
	:	importDefinitions
		(eventDiscriber!)*
		(classDefinition | interfaceDefinition)
		EOF!
		{## = #(#[COMPILATION_UNIT,"COMPILATION_UNIT"],##);}
	;

importDefinitions
	:	(s:importDefinition (e:importDefinition)* )?
		{## = #(#[IMPORTS,"IMPORTS"],##);
		setRegionInfo(##,#s,#e);}
	;

importDefinition
	:	s:"import"! e1:identifierStar (e2:SEMI!)?
		{## = #(#[IMPORT,"IMPORT"],##);
		setRegionInfo(##,#s,#e2==null?#e1:#e2);}
	;

classDefinition
	:	classModifiers
		s:"class"! 
		({LA(1)==IDENT&&LA(2)==LCURLY&&LT(1).getText().equals("TopLevel")}?({isTopLevel=true;}))?
		identifier
		extendsClause
		implementsClause
		e:typeBlock
		{## = #(#[CLASS_DEF,"CLASS_DEF"],##);
		setRegionInfo(##,#s,#e);}
	;
		
interfaceDefinition
	:	s:"interface"! identifier {isInterface = true;}
		extendsClause
		e:typeBlock
		{## = #(#[INTERFACE_DEF,"INTERFACE_DEF"],##);
		setRegionInfo(##,#s,#e);}
	;
extendsClause
	:	(s:"extends"! e:identifier)?
		{## = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],##);
		setRegionInfo(##,#s,#e);}
	;
implementsClause
	:	(s:"implements"! e1:identifier ( COMMA! e2:identifier)*)*
		{## = #(#[IMPLEMENTS_CLAUSE,"IMPLEMENTS_CLAUSE"],##);
		setRegionInfo(##,#s,#e2==null?#e1:#e2);}
	;
typeBlock
	:	s:LCURLY!
		(	typeChild
			|SEMI!
			// macromedia stuff ignore
			|includeStatement! | eventDiscriber!
		)*
		e:RCURLY! ({LA(1)==SEMI}?(SEMI!))?
		{## = #([BLOCK, "BLOCK"], ##);
		setRegionInfo(##,#s,#e);}
	;
typeChild
	:	m:modifiers!
		(	{!isInterface}?
			variableDefinition[#m]
		|	methodDefinition[#m]
		)
	;
methodDefinition[AST mods]
	:	s:FUNCTION! 
		({(LT(1).getText().equals("set")||LT(1).getText().equals("get"))&&LA(2)==IDENT}?(IDENT))?
		(IDENT|{isTopLevel}?specialIdent)
		parameterDeclarationList
		e1:typeSpec
		(e2:block)?
		({LA(1)==SEMI}?(e3:SEMI!))?
		{## = #([METHOD_DEF, "METHOD_DEF"],##,mods);
		setRegionInfo(##,mods.getLine()==-1?#s:mods,#e2==null?(#e3==null?#e1:#e3):(#e3==null?#e2:#e3));}
	;	
	
variableDefinition[AST m]
	:	variableDeclarator[getASTFactory().dupTree(m)]
		(COMMA! variableSubDeclarator[getASTFactory().dupTree(m)])*
		({LA(1)==SEMI}?(SEMI!))?
	;	
	
variableDeclarator[AST mods]
    :   s:"var"! IDENT e1:typeSpec (e2:varInitializer)?
    	({LA(1)==SEMI}?(e3:SEMI!))?
        {## = #(#[VAR_DEF,"VAR_DEF"], ##,mods);
		setRegionInfo(##,mods.getLine()==-1?#s:mods,#e2==null?(#e3==null?#e1:#e3):(#e3==null?#e2:#e3));}
    ;
variableSubDeclarator[AST mods]
    :   s:IDENT e1:typeSpec (e2:varInitializer)?
        {## = #(#[VAR_SUB_DEF,"VAR_SUB_DEF"], ##,mods);
		setRegionInfo(##,#s,#e2==null?#e1:#e2);}
    ;
// A declaration is the creation of a reference or primitive-type variable
// Create a separate Type/Var tree for each var in the var list.
declaration
	:	localVariableDeclarator
		(COMMA! localVariableSubDeclarator)*
	;
localVariableDeclarator
    :   s:"var"! IDENT e1:typeSpec (e2:varInitializer)?
        {## = #(#[VAR_DEF,"VAR_DEF"],##);
		setRegionInfo(##,#s,#e2==null?#e1:#e2);}
    ;
localVariableSubDeclarator
    :   s:IDENT e1:typeSpec (e2:varInitializer)?
        {## = #(#[VAR_SUB_DEF,"VAR_SUB_DEF"],##);
		setRegionInfo(##,#s,#e2==null?#e1:#e2);}
    ;
varInitializer
	:	s:ASSIGN! e:expression
		{## = #(#[VAR_INIT,"VAR_INIT"],##);
		setRegionInfo(##,#s,#e);}
	;	
// A list of formal parameters
parameterDeclarationList
	:	s:LPAREN! ( parameterDeclaration ( COMMA! parameterDeclaration )* )?  e:RPAREN!
		{## = #([PARAMS, "PARAMS"], ##);
		setRegionInfo(##,#s,#e);}
	;
parameterDeclaration
	:	s:IDENT e:typeSpec
		{## = #([PARAM,"PARAM"],##);
		setRegionInfo(##,#s,#e);}
	;
block
	:	s:LCURLY! (statement)* e:RCURLY!
		{## = #([BLOCK, "BLOCK"], ##);
		setRegionInfo(##,#s,#e);}
	;

statement
	:	{LA(1)==LCURLY}?(block)
	|	s1:declaration ({LA(1)==SEMI}?(e1:SEMI!))?
		{setRegionInfo(##,#s1,#e1);}
	|	s21:assignmentExpression ({LA(1)==SEMI}?(e2:SEMI!))?
		{## = #([EXPR_STMNT, "EXPR_STMNT"], ##);
		setRegionInfo(##,#s21,#e2);}
	|	ifStatement
	// For statement
	|	forStatement

	// While statement
	|	"while"^ LPAREN! expression RPAREN! statement

	// do-while statement
	|	"do"^ statement "while"! LPAREN! expression RPAREN!
	
	// with statement
	|	"with"^ LPAREN! expression RPAREN! statement
	
	// switch statement
	|	switchStatement
	
	// get out of a loop (or switch)
	|	breakStatement

	// do next iteration of a loop
	|	continueStatement

	// Return an expression
	|	returnStatement

	// throw an exception
	|	throwStatement
	
	// try and catch
	|	tryStatement

	// empty statement
	|	SEMI!
	;
	
ifStatement
	:	s:"if"^ LPAREN! expression RPAREN! e1:statement
		(	options {greedy=true;}: e2:elseStatement)*
		{setRegionInfo(##,#s,#e2==null?#e1:#e2);}
	;

elseStatement
	:	s:"else"^ e:statement
		{setRegionInfo(##,#s,#e);}
	;
throwStatement
	:	s:THROW^ e1:expression ({LA(1)==SEMI}?(e2:SEMI!))?
		{setRegionInfo(##,#s,#e2==null?#e1:#e2);}
	;
	
tryStatement
	:	s:"try"^ statement  (("catch")=>(e1:catchStatement))? ({LA(1)==SEMI}?(e2:SEMI!))?
		{setRegionInfo(##,#s,#e2==null?#e1:#e2);}
	;
catchStatement
	:	s:"catch"^ LPAREN! parameterDeclaration RPAREN! e:statement
		{setRegionInfo(##,#s,#e);}
	;
returnStatement
	:	s:"return"^ (options {greedy=true;} :e1:expression)? ({LA(1)==SEMI}?(e2:SEMI!))?
		{setRegionInfo(##,#s,#e2==null?#e1:#e2);}
	;
		
continueStatement
	:	s:"continue"^ ({LA(1)==SEMI}?(e:SEMI!))?
		{setRegionInfo(##,#s,#e);}
	;

breakStatement
	:	s:"break"^( {LA(1)==SEMI}?(e:SEMI!))?
		{setRegionInfo(##,#s,#e);}
	;

switchStatement
	:	s:"switch"^ LPAREN! expression RPAREN!
		e:switchBlock
		{setRegionInfo(##,#s,#e);}
	;

switchBlock
	:	s:LCURLY!
		(caseStatement|defaultStatement)*
		e:RCURLY!
		{## = #(#[BLOCK,"BLOCK"], ##);
		setRegionInfo(##,#s,#e);}
	;

caseStatement
	:	s:"case"^ expression e1:COLON! (e2:statement)*
		{setRegionInfo(##,#s,#e2==null?#e1:#e2);}
	;
	
defaultStatement
	:	s:"default"^ e1:COLON! (e2:statement)*
		{setRegionInfo(##,#s,#e2==null?#e1:#e2);}
	;

forStatement
	:	s:"for"^
		(	(LPAREN forInit SEMI)=>traditionalForClause
		|	forInClause
		)
		e:statement					 // statement to loop over
		{setRegionInfo(##,#s,#e);}
	;
traditionalForClause
	:	s:LPAREN!
		forInit SEMI!	// initializer
		forCond SEMI!	// condition test
		forIter			// updater
		e:RPAREN!
		{setRegionInfo(##,#s,#e);}
	;

forInClause
	:	s:LPAREN!
		(declaration|identPrimary) "in"! expression
		e:RPAREN!
		{setRegionInfo(##,#s,#e);}
	;
// The initializer for a for loop
forInit	
	:	((declaration)=> s1:declaration | s2:expressionList )?
		{## = #(#[FOR_INIT,"FOR_INIT"],##);
		setRegionInfo(##,#s2==null?#s1:#s2,null);}
	;

forCond
	:	(s:expression)?
		{## = #(#[FOR_CONDITION,"FOR_CONDITION"],##);
		setRegionInfo(##,#s,null);}
	;

forIter
	:	(s:expressionList)?
		{## = #(#[FOR_ITERATOR,"FOR_ITERATOR"],##);
		setRegionInfo(##,#s,null);}
	;
typeSpec
	:	(	s:COLON! 
			e:identifier 
			{## = #([TYPE_SPEC,"TYPE_SPEC"],##);
			setRegionInfo(##,#s,#e);}
		)?
	;	

identifier 
	:	s:IDENT^
		(	options{greedy=true;}
		: 	DOT! e:IDENT^ 
			{setRegionInfo(##,#s,#e);}
		)*
		{setRegionInfo(##,#s,#e);}
	;

identifierStar
	:	s:IDENT^
		(	options{greedy=true;}
		:	DOT! e1:IDENT^ 
			{setRegionInfo(##,#s,#e1);}
		)* 
		(	DOT! e2:STAR^
			{setRegionInfo(##,#s,#e2);}
		)?
		{setRegionInfo(##,#s,#e2==null?#e1:#e2);}
	;
classModifiers
	:	(s:classModifier (e:classModifier)*)?
		{## = #([MODIFIERS, "MODIFIERS"], ##);
		setRegionInfo(##,#s,#e);}
	;
classModifier
	:	"dynamic"
	|	"intrinsic" { isIntrinsic = true; }
	;
modifiers
	:	( s:modifier (e:modifier)* )?
		{## = #([MODIFIERS, "MODIFIERS"],##);
		setRegionInfo(##,#s,#e);}
	;
modifier
	:	"private"
	|	"public"
	|	"static"
	;

arguments
	:	(expressionList)?
	;
// This is an initializer used to set up an array.
arrayLiteral
	:	s:LBRACK! elementList e:RBRACK!
		{## = #([ARRAY_LITERAL,"ARRAY_LITERAL"],##);
		setRegionInfo(##,#s,#e);}
	;
		
elementList
	:	(element)?
		(COMMA! (element)?)*
	;
element
	:	s:assignmentExpression
		{## = #([ELEMENT,"ELEMENT"],##);
		setRegionInfo(##,#s,null);}
	;
	
// This is an initializer used to set up an object.
objectLiteral
	:	s:LCURLY! (fieldList)? e:RCURLY!
		{## = #([OBJECT_LITERAL,"OBJECT_LITERAL"],##);
		setRegionInfo(##,#s,#e);}
	;
	
fieldList
	:	literalField (COMMA! (literalField)?)*
	;
	
literalField 
	: 	s:fieldName COLON! e:element
		{## = #([OBJECT_FIELD,"OBJECT_FIELD"],##);
		setRegionInfo(##,#s,#e);}
	;
	
fieldName
	:	IDENT
	|	NUMBER
	;

// the mother of all expressions
expression
	:	s:assignmentExpression
		{## = #(#[EXPR,"EXPR"],##);
		setRegionInfo(##,#s,null);}
	;

// This is a list of expressions.
expressionList
	:	s:expression (COMMA! e:expression)*
		{## = #(#[ELIST,"ELIST"], ##);
		setRegionInfo(##,#s,#e);}
	;

// assignment expression (level 13)
assignmentExpression
	:	s:conditionalExpression
		(	(	(	ASSIGN!
				| 	STAR_ASSIGN!
				|	DIV_ASSIGN!
				|	MOD_ASSIGN!
				|	PLUS_ASSIGN!
				|	MINUS_ASSIGN!
				|	SL_ASSIGN!
				|	SR_ASSIGN!
				|	BSR_ASSIGN!
				|	BAND_ASSIGN!
				|	BXOR_ASSIGN!
				|	BOR_ASSIGN!
				)	~ASSIGN
			)=>
			(	ASSIGN^ 
			| 	STAR_ASSIGN^
			|	DIV_ASSIGN^
			|	MOD_ASSIGN^
			|	PLUS_ASSIGN^
			|	MINUS_ASSIGN^
			|	SL_ASSIGN^
			|	SR_ASSIGN^
			|	BSR_ASSIGN^
			|	BAND_ASSIGN^
			|	BXOR_ASSIGN^
			|	BOR_ASSIGN^
			)
			e:assignmentExpression
			{setRegionInfo(##,#s,#e);}
		)?
	;
	
// conditional test (level 12)
conditionalExpression
	:	s:logicalOrExpression 
		(	options {greedy=true;} 
		:	QUESTION^ 
			e:conditionalSubExpression
			{setRegionInfo(##,#s,#e);}
		)*
	;
conditionalSubExpression
	:	s:assignmentExpression COLON^ e:assignmentExpression
		{setRegionInfo(##,#s,#e);}
	;
// logical or (||)  (level 11)
logicalOrExpression
	:	s:logicalAndExpression 
		(	(LOR^|"or"^) e:logicalAndExpression
			{setRegionInfo(##,#s,#e);}
		)*
	;
// logical and (&&)  (level 10)
logicalAndExpression
	:	s:bitwiseOrExpression 
		(	(LAND^|"and"^) e:bitwiseOrExpression
			{setRegionInfo(##,#s,#e);}
		)*
	;
// bitwise or non-short-circuiting or (|)  (level 9)
bitwiseOrExpression
	:	s:bitwiseXorExpression 
		(	BOR^ e:bitwiseXorExpression
			{setRegionInfo(##,#s,#e);}
		)*
	;	
// exclusive or (^)  (level 8)
bitwiseXorExpression
	:	s:bitwiseAndExpression 
		(	BXOR^ e:bitwiseAndExpression
			{setRegionInfo(##,#s,#e);}
		)*
	;
// bitwise or non-short-circuiting and (&)  (level 7)
bitwiseAndExpression
	:	s:equalityExpression 
		(	BAND^ e:equalityExpression
			{setRegionInfo(##,#s,#e);}
		)*
	;
// equality/inequality (==/!=) (level 6)
equalityExpression
	:	s:relationalExpression 
		(	( STRICT_EQUAL^ | STRICT_NOT_EQUAL^ | NOT_EQUAL^ | EQUAL^ )
			e:relationalExpression
			{setRegionInfo(##,#s,#e);}
		)*
	;
// boolean relational expressions (level 5)
relationalExpression
	:	s:shiftExpression 
		(	(LT^ | GT^ | LE^ | GE^ | INSTANCEOF^) e:shiftExpression
			{setRegionInfo(##,#s,#e);}
		)*
	;
		
// bit shift expressions (level 4)
shiftExpression
	:	s:additiveExpression 
		(	(SL^ | SR^ | BSR^) e:additiveExpression
			{setRegionInfo(##,#s,#e);}
		)*
	;
		
// binary addition/subtraction (level 3)
additiveExpression
	:	s:multiplicativeExpression 
		(	options {greedy=true;} 
		:	(PLUS^ | MINUS^) e:multiplicativeExpression
			{setRegionInfo(##,#s,#e);}
		)*
	;
// multiplication/division/modulo (level 2)
multiplicativeExpression
	:	s:unaryExpression 
		(	(STAR^ | DIV^ | MOD^) e:unaryExpression
			{setRegionInfo(##,#s,#e);}
		)*
	;
//	(level 1)
unaryExpression
	:	INC^ unaryExpression
	|	DEC^ unaryExpression
	|	MINUS^ 	{#MINUS.setType(UNARY_MINUS);} unaryExpression
	|	PLUS^ 	{#PLUS.setType(UNARY_PLUS);}   unaryExpression
	|	unaryExpressionNotPlusMinus
	;
unaryExpressionNotPlusMinus
	:	DELETE^ postfixExpression
	|	TYPEOF^ postfixExpression
	|	"void" unaryExpression
	|	LNOT^ unaryExpression
	|	BNOT^ unaryExpression
	|	postfixExpression
	;
// qualified names, array expressions, method invocation, post inc/dec
postfixExpression
	:	s:primaryExpression
		(	options{greedy=true;} :
			(	DOT! e1:IDENT^
				{setRegionInfo(#e1,#s,#e1);}
			|	(	t1:LBRACK^ expression e2:RBRACK!
					{#t1.setType(ARRAY_ACC);
					#t1.setText("ARRAY_ACC");
					setRegionInfo(#t1,#s,#e2);}
				)
			)
			(	options {greedy=true;}
			:	t2:LPAREN^ arguments e3:RPAREN! 
				{#t2.setType(METHOD_CALL);
				#t2.setText("METHOD_CALL");
				setRegionInfo(#t2,#s,#e3);}
				(	options {greedy=true;}
				:	t3:LPAREN^ arguments e4:RPAREN! 
					{#t3.setType(METHOD_CALL);
					#t3.setText("METHOD_CALL");
					setRegionInfo(#t3,#s,#e4);}
				)*
			)?
		)*
		(	options {greedy=true;} 
		: 	in:INC^ {#in.setType(POST_INC);}
	 	|	de:DEC^ {#de.setType(POST_DEC);}
		)?
 	;
 	
primaryExpression
	:	identPrimary
	|	NULL
	|	TRUE
	|	FALSE
	|	UNDEFINED
    |   constant
	|	arrayLiteral
	|	objectLiteral
    |	functionDefinition
    |	newExpression
    |	THIS
    |	encapsulatedExpression
	;

identPrimary
	:	s:IDENT
		(	options{greedy=true;}
		:	DOT! e1:IDENT^
			{setRegionInfo(#e1,#s,#e1);}
		|	(	t1:LBRACK^ expression e2:RBRACK!
				{#t1.setType(ARRAY_ACC);
				#t1.setText("ARRAY_ACC");
				setRegionInfo(#t1,#s,#e2);}
			)
		)*
		(	options {greedy=true;}
		:	t2:LPAREN^ arguments e3:RPAREN! 
			{#t2.setType(METHOD_CALL);
			#t2.setText("METHOD_CALL");
			setRegionInfo(#t2,#s,#e3);}
		)*
    ;

constant
	:	NUMBER
	|	STRING_LITERAL
	;
newExpression
	:	s:NEW! e:postfixExpression
		{## = #([NEW_EXPR,"NEW_EXPR"],##);
		setRegionInfo(##,#s,#e);}
	;
encapsulatedExpression
	:	s:LPAREN! assignmentExpression e:RPAREN!
		{## = #([ENCPS_EXPR,"ENCPS_EXPR"],##);
		setRegionInfo(##,#s,#e);}
	;	
	
functionDefinition
	:	s:FUNCTION parameterDeclarationList typeSpec e:block
		{## = #([FUNC_DEF,"FUNC_DEF"],##);
		setRegionInfo(##,#s,#e);}
	;
specialIdent
	:	(	DELETE
		|	TYPEOF
		|	INSTANCEOF
		|	THROW
		)
		{ ##.setType(IDENT);}
	;
//macromedia stuff ignored
includeStatement
	:   INCLUDE STRING_LITERAL
	;
eventDiscriber
	:	LBRACK (~RBRACK)* RBRACK
	;
class AS2Lexer extends Lexer;

options {
	exportVocab=AS2;      	// call the vocabulary "AS2"
	testLiterals=true;    	// don't automatically test for literals
	k=4;                   	// four characters of lookahead
	charVocabulary='\u0003'..'\u7FFE';
	codeGenBitsetTestThreshold=20;
	defaultErrorHandler=false;
}
{
	private List<Token> commentList;
	private void addComment(Token t){
		if(commentList==null) commentList = new ArrayList<Token>();
		commentList.add(t);
	}
	public List getComments(){
		return commentList;	
	}
}
// OPERATORS
QUESTION		:	'?'		;
LPAREN			:	'('		;
RPAREN			:	')'		;
LBRACK			:	'['		;
RBRACK			:	']'		;
LCURLY			:	'{'		;
RCURLY			:	'}'		;
COLON			:	':'		;
COMMA			:	','		;
//DOT				:	'.'	; //declared in number
ASSIGN			:	'='		;
EQUAL			:	"=="	;
STRICT_EQUAL	:	"==="	;
LNOT			:	'!'		;
BNOT			:	'~'		;
NOT_EQUAL		:	"!="	;
STRICT_NOT_EQUAL:	"!=="	;
DIV				:	'/'		;
DIV_ASSIGN		:	"/="	;
PLUS			:	'+'		;
PLUS_ASSIGN		:	"+="	;
INC				:	"++"	;
MINUS			:	'-'		;
MINUS_ASSIGN	:	"-="	;
DEC				:	"--"	;
STAR			:	'*'		;
STAR_ASSIGN		:	"*="	;
MOD				:	'%'		;
MOD_ASSIGN		:	"%="	;
SR				:	">>"	;
SR_ASSIGN		:	">>="	;
BSR				:	">>>"	;
BSR_ASSIGN		:	">>>="	;
GE				:	">="	;
GT				:	">"		;
SL				:	"<<"	;
SL_ASSIGN		:	"<<="	;
LE				:	"<="	;
LT				:	'<'		;
BXOR			:	'^'		;
BXOR_ASSIGN		:	"^="	;
BOR				:	'|'		;
BOR_ASSIGN		:	"|="	;
LOR				:	"||"	;
BAND			:	'&'		;
BAND_ASSIGN		:	"&="	;
LAND			:	"&&"	;
SEMI			:	';'		;

// an identifier.  Note that testLiterals is set to true!  This means
// that after we match the rule, we look in the literals table to see
// if it's a literal or really an identifer
IDENT options {testLiterals=true;}
	:	('a'..'z'|'A'..'Z'|'_'|'$') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|'$')*
	;
	
STRING_LITERAL
	:	'"' 	
		(	options {generateAmbigWarnings=false;} 
		: 	ESC | ~('"'|'\n'|'\r'))* 
		'"'
	|	'\'' 	
		(	options {generateAmbigWarnings=false;}
		:	ESC | ~('\''|'\n'|'\r'))*
		'\''
	;

NUMBER {Token t=null;} // dot could start a number
	:	'.' {_ttype = DOT;} (('0'..'9')+ (EXPONENT)? {_ttype = NUMBER;})?
	|	(	'0' 
			(	('X'|'x') (options {warnWhenFollowAmbig = false;}:HEX_DIGIT)+
			|	(('0'..'9')* ('.' ('0'..'9')+)?  (EXPONENT)?) 
			=>   ('0'..'9')* ('.' ('0'..'9')+)?  (EXPONENT)?
			|	('0'..'7')+
			)?
		|	('1'..'9') ('0'..'9')* ('.' ('0'..'9')+)?  (EXPONENT)?
		)	{_ttype = NUMBER;}
	;

// whitespace -- ignored
WS	:	(	' '
		|	'\t'
		|	'\f'
			// skip bom chars
		| 	'\u00EF' | '\u00BB'|'\u00BF' 
			// handle newlines
		|	NL
		)+
		{ _ttype = Token.SKIP; }
	;
protected NL	
	:	(	options {generateAmbigWarnings=false;}
		:	'\r' '\n'  	// DOS
		|	'\r'    	// Mac
		|	'\n'    	// Unix
		)
		{ newline(); _ttype = Token.SKIP;}
	;
// single-line comments
SL_COMMENT
	:	"//" (~('\n'|'\r'))* ('\n'|'\r'('\n')?)?
		{
			Token _mytoken = makeToken(_ttype);
			_mytoken.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
		 	addComment(_mytoken);
		 	$setType(Token.SKIP);
		 	newline();
		 }
	;
// multiple-line comments
ML_COMMENT
	:	"/*"
		(	options {generateAmbigWarnings=false;}
		:
			{ LA(2)!='/' }? '*'
		|	NL
		|	~('*'|'\n'|'\r')
		)*
		"*/"
		{
			Token _mytoken = makeToken(_ttype);
			_mytoken.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
		 	addComment(_mytoken);
		 	$setType(Token.SKIP);
		 }
	;
/* protected will not directly be 
 * returned to the parser
 */
protected EXPONENT
	:	('e'|'E') ('+'|'-')? ('0'..'9')+
	;
protected HEX_DIGIT
	:	('0'..'9'|'A'..'F'|'a'..'f')
	;
	
protected ESC
	:	'\\'
		(	'\\'|'n'|'r'|'t'|'b'|'f'|'"'|'\''
		|	('u')+ HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
		|	'0'..'3'
			( options{warnWhenFollowAmbig = false;}
			:	'0'..'7'( options{warnWhenFollowAmbig = false;}:'0'..'7')?
			)?
		|	'4'..'7'
			( options{warnWhenFollowAmbig = false;}
			:	'0'..'7'
			)?
		)
	;
//macromedia stuff ignored
INCLUDE
	: "#include"
	;